package top.ninwoo.utils.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.ninwoo.utils.entity.LinkInfo;
import top.ninwoo.utils.entity.NetworkInfo;
import top.ninwoo.utils.service.TcService;
import top.ninwoo.utils.util.DockerUtils;
import top.ninwoo.utils.util.TcUtils;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author joliu
 * @Description
 * @Date　Create in 下午3:34 2019/11/1
 */
@Service
public class TcServiceImpl implements TcService {
    // 这里需要设计成有状态的
    private ConcurrentHashMap<String, Integer> qosMap = new ConcurrentHashMap<>();
    private ConcurrentHashMap<String, LinkInfo> delayMap = new ConcurrentHashMap<>();

    @Autowired
    TcUtils tcUtils;

    @Autowired
    DockerUtils dockerUtils;

    @Override
    public boolean addQos(String containerId, String maxRate, String latency) {
        // 添加到map中
        if(qosMap.containsKey(containerId)) {
            delQos(containerId);
        }
        qosMap.put(containerId, Integer.parseInt(maxRate.substring(0, maxRate.length() - 4)));
        return tcUtils.addQos(containerId, maxRate, latency);
    }

    @Override
    public boolean delQos(String containerId) {
        if(qosMap.containsKey(containerId)) {
            qosMap.remove(containerId);
            return tcUtils.delQos(containerId);
        }
        return true;
    }

    /**
     * 测试docker容器的网络实时速率
     * @param containerId
     * @return
     * @throws InterruptedException
     */
    @Override
    public NetworkInfo networkUsage(String containerId) throws InterruptedException {
        NetworkInfo networkInfo = new NetworkInfo();
        float netUsage = 0.0f;
        String command = "cat /proc/net/dev";
        long startTime = System.currentTimeMillis();
        String[] lines = dockerUtils.execInDocker(containerId, command.split(" ")).split("\n");
        int i = 0;
        long inSize1 = 0, outSize1 = 0;
        long  packetIn1 = 0, packetOut1 = 0;
        long errorIn1 = 0, errorOut1 = 0;
        long dropIn1 = 0, dropOut1 = 0;
        while(i < lines.length){
            String line = lines[i++];
            line = line.trim();
            if(line.startsWith("eth1")){
                String[] temp = line.split("\\s+");
                inSize1 = Long.parseLong(temp[1]); //Receive bytes,单位为Byte
                outSize1 = Long.parseLong(temp[9]);             //Transmit bytes,单位为Byte
                packetIn1 = Long.parseLong(temp[2]);
                packetOut1 = Long.parseLong(temp[10]);
                errorIn1 = Long.parseLong(temp[3]);
                errorOut1 = Long.parseLong(temp[11]);
                dropIn1 = Long.parseLong(temp[4]);
                dropOut1 = Long.parseLong(temp[12]);
                break;
            }
        }
        Thread.sleep(500);
        long endTime = System.currentTimeMillis();
        lines = dockerUtils.execInDocker(containerId, command.split(" ")).split("\n");
        i = 0;
        long inSize2 = 0 ,outSize2 = 0;
        long packetIn2 = 0, packetOut2 = 0;
        long errorIn2 = 0, errorOut2 = 0;
        long dropIn2 = 0, dropOut2 = 0;
        while(i < lines.length){
            String line = lines[i++];
            line = line.trim();
            if(line.startsWith("eth1")){
                String[] temp = line.split("\\s+");
                inSize2 = Long.parseLong(temp[1]);
                outSize2 = Long.parseLong(temp[9]);
                packetIn2 = Long.parseLong(temp[2]);
                packetOut2 = Long.parseLong(temp[10]);
                errorIn2 = Long.parseLong(temp[3]);
                errorOut2 = Long.parseLong(temp[11]);
                dropIn2 = Long.parseLong(temp[4]);
                dropOut2 = Long.parseLong(temp[12]);
                break;
            }
        }
        if(inSize1 != 0 && outSize1 !=0 && inSize2 != 0 && outSize2 !=0){
            float interval = (float)(endTime - startTime)/1000;

            float curRate = (float)(inSize2 - inSize1 + outSize2 - outSize1)*8/(1000000*interval);
            float errorRate = (float)(errorIn2 - errorIn1 + errorOut2 - errorOut1) /
                    (packetIn2 - packetIn1 + packetOut2 - packetOut1);
            float dropRate = (float) (dropIn2 - dropIn1 + dropOut2 - dropOut1) /
                    (packetIn2 - packetIn1 + packetOut2 - packetOut1);
            int maxRate = 1000;
            if(qosMap.containsKey(containerId)) {
                maxRate = qosMap.get(containerId);
            }
            netUsage = curRate/maxRate;
            if(netUsage > 1.0) {
                netUsage = 1.0f;
            }
            networkInfo.setCurRate(curRate);
            networkInfo.setDropRate(dropRate);
            networkInfo.setErrorRate(errorRate);
            networkInfo.setContainerId(containerId);
        }
        return networkInfo;
    }

    @Override
    public boolean addDelay(String containerId, int delay, int randomDelay, int correlation) {
        String mode = "add";
        if (delayMap.containsKey(containerId)) {
            mode = "change";
        }
        LinkInfo linkInfo = new LinkInfo();
        linkInfo.setCorrelation(0);
        linkInfo.setPolicy("");
        linkInfo.setRandomDelay(randomDelay);
        linkInfo.setDelay(delay);
        delayMap.put(containerId, linkInfo);
        return tcUtils.addDelay(containerId, mode, delay, randomDelay, correlation);
    }
    // TODO:这里还可以添加更多实现的接口
    @Override
    public boolean addDelay(String containerId, int loss) {
        String mode = "add";
        if(delayMap.containsKey(containerId)) {
            mode = "change";
        }
        LinkInfo linkInfo = new LinkInfo();
        linkInfo.setLoss(0);
        delayMap.put(containerId, linkInfo);
        return tcUtils.addDelay(containerId, mode, 0, 0, 0, loss);
    }

    @Override
    public boolean addDelay(String containerId) {
        return false;
    }
}